package TI;

import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import Exceptions.NotEnoughStockException;
import Exceptions.ProductSalesPriceNeverSetException;
import Magnitudes.Money;
import Magnitudes.Pesos;
import Products.Presentation;

import junit.framework.TestCase;
import static org.mockito.Mockito.*;

public class BranchOfficeTest extends TestCase {

	BranchOffice branchOfficeToTest;
	Systemo systemo = mock(Systemo.class);
	Address address = mock(Address.class);
	Storehouse storehouse = mock(Storehouse.class);
	Storehouse anotherStorehouse = mock(Storehouse.class);
	ParticularCustomer customer = mock(ParticularCustomer.class);
	Presentation presentation = mock(Presentation.class);
	
	@Before
	public void setUp(){
		branchOfficeToTest = new BranchOffice(address, systemo);
		try {
			when(presentation.getUnitSalesPrice()).thenReturn(new Pesos(100));
		} catch (ProductSalesPriceNeverSetException e) {
			e.printStackTrace();
		}
	}
	
	@Test
	public void testGivenABranchOfficeJustCreatedWhenGetSalesShouldBeEmpty(){
		assertTrue(branchOfficeToTest.getSales().isEmpty());
	}
	
	@Test
	public void testGivenABranchOfficeJustCreatedWhenGetCashShouldReturnPesosMil(){
		assertTrue(new Pesos(1000).amount() == (branchOfficeToTest.getCash().amount()));
	}
	
	@Test
	public void testGivenABranchOfficeJustCreatedWhenGetStorehousesShouldBeEmpty(){
		assertTrue(branchOfficeToTest.getStorehouses().isEmpty());
	}
	
	@Test
	public void testGivenABranchOfficeWhenAssociateStorehouseGetStorehousesShouldContainsThatOne(){
		branchOfficeToTest.associateStorehouse(storehouse);
		assertTrue(branchOfficeToTest.getStorehouses().contains(storehouse));
	}
	
	@Test
	public void testGivenABranchOfficeWhenAddCustomerShouldSendTheMessageToTheSystemo(){
		branchOfficeToTest.addCustomer(customer);
		verify(systemo).addCustomer(customer);
	}
	
	@Test
	public void testGivenABranchOfficeWithTwoStorehousesWhenCheckAcalabilityOfProductShouldAskToEveryStorehouse(){
		branchOfficeToTest.associateStorehouse(storehouse);
		branchOfficeToTest.associateStorehouse(anotherStorehouse);
		branchOfficeToTest.checkAvailability(presentation);
	
		verify(storehouse).isAvailable(presentation);
		verify(anotherStorehouse).isAvailable(presentation);
	}
	
	@Test
	public void testGivenABranchOfficeWithTwoStorehouseWhenReceivePresentationShouldSendHalfAndHalfOfPresentation(){
		branchOfficeToTest.associateStorehouse(storehouse);
		branchOfficeToTest.receivePresentations(presentation, 10, new Pesos(100));
		verify(storehouse).receive(presentation, 10);
	}
	
	@Test
	public void testGivenABranchOfficeWhenRegisterQuickBuyShouldCreateTheSale(){
		List<Presentation> products = new ArrayList<Presentation>();
		products.add(presentation);
		assertEquals(0, branchOfficeToTest.getSales().size());
		try {
			branchOfficeToTest.registerQuickBuy(customer, products);
		} catch (ProductSalesPriceNeverSetException e) {
			e.printStackTrace();
		}
		assertEquals(1, branchOfficeToTest.getSales().size());
	}
	
//	@Test
//	public void testGivenABranchOfficeWhenRegisterQuickBuyShouldDecreaseStorehouseStock(){
//		List<Presentation> products = new ArrayList<Presentation>();
//		products.add(presentation);
//		BranchOffice spyBranch = spy(branchOfficeToTest);
//		when((spyBranch.getStorehouses()).at(0)).shouldReturn(storehouse);
//		spyBranch.registerQuickBuy(customer, products);
//		verify(storehouse).deliver(presentation, 1);
//	}
	
	@Test
	public void testGivenABranchOfficeWhenRegisterQuickBuyShouldIncreaseCash(){
		List<Presentation> products = new ArrayList<Presentation>();
		products.add(presentation);
		Pesos previus = (Pesos) branchOfficeToTest.getCash();
		try {
			when(presentation.getUnitSalesPrice()).thenReturn(new Pesos(100));
		} catch (ProductSalesPriceNeverSetException e) {
			e.printStackTrace();
		}
		try {
			branchOfficeToTest.registerQuickBuy(customer, products);
		} catch (ProductSalesPriceNeverSetException e) {
			e.printStackTrace();
		}
		assertTrue((previus.add(new Pesos(100))).amount() == (branchOfficeToTest.getCash()).amount());
	}
	// Falta en parte del comportamiento cuando se realiza la venta
	
}
